package task

import (
	"encoding/json"
	"pids-cloud-server/constants"
	"pids-cloud-server/entity"
	"pids-cloud-server/logging"
	"pids-cloud-server/utils"
	"strconv"
	"time"

	"github.com/google/uuid"
	"gorm.io/gorm/clause"
)

// 上次初始化时间
var lastInitTime time.Time

func CommitTask() {
	start := time.Now()
	logging.Info("---------批量提交监控数据任务开始---------")

	// 获取数据库连接
	db := utils.GetDB()
	if db == nil {
		logging.Error("数据库连接失败，跳过CommitTask")
		return
	}

	var alarmThresholdList []entity.AlarmThreshold
	db.Find(&alarmThresholdList)
	var alarmList []entity.AlarmInfo
	// 增量初始化告警管理器
	incrementalInitializeAlarmManager()

	//处理网络告警
	if utils.LLen(constants.NETWORK_STATE_LIST) > 0 {
		networkStateJsonStr := utils.LRange(constants.NETWORK_STATE_LIST, 0, -1)
		utils.Del(constants.NETWORK_STATE_LIST)
		latestNetworkMap := make(map[string]entity.NetworkState)
		for i := range networkStateJsonStr {
			if networkStateJsonStr[i] != "" {
				var networkState entity.NetworkState
				// 先解码到临时变量 networkState
				err := json.Unmarshal([]byte(networkStateJsonStr[i]), &networkState)
				if err != nil {
					logging.Error("解析网络数据失败:" + err.Error())
				}
				if _, exists := latestNetworkMap[networkState.HostName]; !exists || networkState.CreateTime.After(latestNetworkMap[networkState.HostName].CreateTime) {
					latestNetworkMap[networkState.HostName] = networkState
				}
			}
		}
		//网络告警数据生成
		for _, networkState := range latestNetworkMap {
			var alarmType entity.AlarmType
			var alarmDetail string
			switch networkState.Type {
			case entity.NTP:
				alarmType = entity.NTP_ERROR
				alarmDetail = "一级告警:" + networkState.HostName + ";NTP异常"
			case entity.WiFiDevice:
				alarmType = entity.WIFI_ERROR
				alarmDetail = "一级告警:" + networkState.HostName + ";WiFi异常"
			case entity.VehicleGroundRadio:
				alarmType = entity.VEHICLE_GROUND_RADIO_ERROR
				alarmDetail = "一级告警:" + networkState.HostName + ";车地无线异常"
			case entity.VehicleDumpRadio:
				alarmType = entity.VEHICLE_DUMP_RADIO_ERROR
				alarmDetail = "一级告警:" + networkState.HostName + ";车地无线转储异常"
			case entity.WorkStation:
				alarmType = entity.WORKSTATION_ERROR
				alarmDetail = "一级告警:" + networkState.HostName + ";工作站异常"
			default:
				alarmType = entity.NETWORK_ERROR
				alarmDetail = "一级告警:" + networkState.HostName + ";网络故障"
			}
			// 检查是否已存在该类型告警
			existingAlarm, exists := constants.GlobalAlarmManager.GetAlarm(networkState.HostName, alarmType)
			if networkState.Status == entity.OFFLINE {
				// 创建或更新告警信息
				alarmInfo := entity.AlarmInfo{
					ID:         uuid.NewString(),
					Type:       alarmType,
					Detail:     alarmDetail,
					HostIP:     networkState.HostName,
					LevelID:    1,
					Flag:       networkState.Type,
					Status:     entity.ACTIVE,
					CreateTime: time.Now(),
					ModifyTime: time.Now(),
				}
				if exists {
					// 如果已存在告警，保留原ID和创建时间
					alarmInfo.ID = existingAlarm.ID
					alarmInfo.CreateTime = existingAlarm.CreateTime
				}
				// 添加到告警列表
				alarmList = append(alarmList, alarmInfo)
				// 更新告警管理器
				constants.GlobalAlarmManager.SetAlarm(networkState.HostName, alarmInfo)
			} else {
				// 检查是否需要告警恢复
				if exists {
					// 设置告警为非活跃状态
					existingAlarm.Status = entity.INACTIVE
					existingAlarm.ModifyTime = time.Now()
					alarmList = append(alarmList, existingAlarm)
					// 更新告警管理器
					constants.GlobalAlarmManager.SetAlarm(networkState.HostName, existingAlarm)
				}
			}
		}
	}

	alarmThresholdMap := make(map[string]entity.AlarmThreshold)
	for _, alarmThreshold := range alarmThresholdList {
		alarmThresholdMap[alarmThreshold.HostIP] = alarmThreshold
	}
	//处理cpu告警
	if utils.LLen(constants.CPU_STATE_LIST) > 0 {
		cpuStateJsonStr := utils.LRange(constants.CPU_STATE_LIST, 0, -1)
		utils.Del(constants.CPU_STATE_LIST)
		latestCpuMap := make(map[string]entity.CpuState)
		for i := range cpuStateJsonStr {
			if cpuStateJsonStr[i] != "" {
				var cpuState entity.CpuState
				err := json.Unmarshal([]byte(cpuStateJsonStr[i]), &cpuState)
				if err != nil {
					logging.Error("解析CPU状态数据失败:" + err.Error())
				}
				if _, exists := latestCpuMap[cpuState.HostName]; !exists || cpuState.CreateTime.After(latestCpuMap[cpuState.HostName].CreateTime.Time) {
					latestCpuMap[cpuState.HostName] = cpuState
				}
			}
		}
		//生成CPU告警数据
		for _, cpuState := range latestCpuMap {
			alarmThreshold, exists := alarmThresholdMap[cpuState.HostName]
			var alarmLevel int
			var alramDetail string
			if exists {
				if cpuState.Sys > float64(alarmThreshold.CPUMax) && alarmThreshold.CPUMaxEnable == 1 {
					alarmLevel = 1
					alramDetail = "一级告警:" + cpuState.HostName + ";CPU使用率:" + strconv.FormatFloat(cpuState.Sys, 'f', -1, 64) + ">" + strconv.Itoa(alarmThreshold.CPUMax)
				} else if cpuState.Sys > float64(alarmThreshold.CPUNor) && alarmThreshold.CPUNorEnable == 1 {
					alarmLevel = 2
					alramDetail = "二级告警:" + cpuState.HostName + ";CPU使用率:" + strconv.FormatFloat(cpuState.Sys, 'f', -1, 64) + ">" + strconv.Itoa(alarmThreshold.CPUNor)
				} else if cpuState.Sys > float64(alarmThreshold.CPUMin) && alarmThreshold.CPUMinEnable == 1 {
					alarmLevel = 3
					alramDetail = "三级告警:" + cpuState.HostName + ";CPU使用率:" + strconv.FormatFloat(cpuState.Sys, 'f', -1, 64) + ">" + strconv.Itoa(alarmThreshold.CPUMin)
				}
			}
			//告警更新原则: 告警等级上升则更新告警记录即可，告警等级下降的过程，关闭高级告警，新增一条当前等级的告警记录
			//告警等级>0 说明有告警产生
			if alarmLevel > 0 {
				// 创建或更新告警信息
				alarmInfo := entity.AlarmInfo{
					ID:         uuid.NewString(),
					LevelID:    alarmLevel,
					Detail:     alramDetail,
					HostIP:     cpuState.HostName,
					Type:       entity.CPU_ERROR,
					CreateTime: time.Now(),
					ModifyTime: time.Now(),
					Status:     entity.ACTIVE,
					Flag:       cpuState.Type,
				}
				// 检查是否已存在该类型告警
				existingAlarm, exists := constants.GlobalAlarmManager.GetAlarm(cpuState.HostName, entity.CPU_ERROR)
				if exists {
					// 如果已存在告警，保留原ID和创建时间
					alarmInfo.ID = existingAlarm.ID
					alarmInfo.CreateTime = existingAlarm.CreateTime

					// 如果新告警等级严重性低于已有告警等级，关闭已有告警，创建新告警。alarmLevel值越小，告警越严重
					if alarmLevel > existingAlarm.LevelID {
						existingAlarm.Status = entity.INACTIVE
						existingAlarm.ModifyTime = time.Now()
						alarmList = append(alarmList, existingAlarm)
					}
				}
				// 添加到告警列表
				alarmList = append(alarmList, alarmInfo)
				// 更新告警管理器
				constants.GlobalAlarmManager.SetAlarm(cpuState.HostName, alarmInfo)
			} else {
				//没有产生告警，检查是否需要告警恢复
				existingAlarm, exists := constants.GlobalAlarmManager.GetAlarm(cpuState.HostName, entity.CPU_ERROR)
				if exists {
					// 设置告警为非活跃状态
					existingAlarm.Status = entity.INACTIVE
					existingAlarm.ModifyTime = time.Now()
					alarmList = append(alarmList, existingAlarm)

					// 更新告警管理器
					constants.GlobalAlarmManager.SetAlarm(cpuState.HostName, existingAlarm)
				}
			}
		}
	}
	//处理磁盘告警
	if utils.LLen(constants.DISK_STATE_LIST) > 0 {
		diskStateJsonStr := utils.LRange(constants.DISK_STATE_LIST, 0, -1)
		utils.Del(constants.DISK_STATE_LIST)
		latestDiskMap := make(map[string]entity.DeskState)
		for i := range diskStateJsonStr {
			if diskStateJsonStr[i] != "" {
				var diskState entity.DeskState
				err := json.Unmarshal([]byte(diskStateJsonStr[i]), &diskState)
				if err != nil {
					logging.Error("解析磁盘状态数据失败:" + err.Error())
				}
				if _, exists := latestDiskMap[diskState.HostName]; !exists || diskState.CreateTime.After(latestDiskMap[diskState.HostName].CreateTime.Time) {
					latestDiskMap[diskState.HostName] = diskState
				}
			}
		}
		//生成磁盘告警
		for _, diskState := range latestDiskMap {
			alarmThreshold, exists := alarmThresholdMap[diskState.HostName]
			var alarmLevel int
			var alramDetail string
			if exists {
				if diskState.UsePer > float64(alarmThreshold.DiskMax) && alarmThreshold.DiskMaxEnable == 1 {
					alarmLevel = 1
					alramDetail = "一级告警:" + diskState.HostName + ";磁盘使用率:" + strconv.FormatFloat(diskState.UsePer, 'f', -1, 64) + ">" + strconv.Itoa(alarmThreshold.DiskMax)
				} else if diskState.UsePer > float64(alarmThreshold.DiskNor) && alarmThreshold.DiskNorEnable == 1 {
					alarmLevel = 2
					alramDetail = "二级告警:" + diskState.HostName + ";磁盘使用率:" + strconv.FormatFloat(diskState.UsePer, 'f', -1, 64) + ">" + strconv.Itoa(alarmThreshold.DiskNor)
				} else if diskState.UsePer > float64(alarmThreshold.DiskMin) && alarmThreshold.DiskMinEnable == 1 {
					alarmLevel = 3
					alramDetail = "三级告警:" + diskState.HostName + ";磁盘使用率:" + strconv.FormatFloat(diskState.UsePer, 'f', -1, 64) + ">" + strconv.Itoa(alarmThreshold.DiskMin)
				}
			}
			//告警更新原则: 告警等级上升则更新告警记录即可，告警等级下降的过程，关闭高级告警，新增一条当前等级的告警记录
			//告警等级>0 说明有告警产生
			if alarmLevel > 0 {
				// 创建或更新告警信息
				alarmInfo := entity.AlarmInfo{
					ID:         uuid.NewString(),
					LevelID:    alarmLevel,
					Detail:     alramDetail,
					HostIP:     diskState.HostName,
					Type:       entity.DISK_ERROR,
					CreateTime: time.Now(),
					ModifyTime: time.Now(),
					Status:     entity.ACTIVE,
					Flag:       diskState.Type,
				}
				// 检查是否已存在该类型告警
				existingAlarm, exists := constants.GlobalAlarmManager.GetAlarm(diskState.HostName, entity.DISK_ERROR)
				if exists {
					// 如果已存在告警，保留原ID和创建时间
					alarmInfo.ID = existingAlarm.ID
					alarmInfo.CreateTime = existingAlarm.CreateTime
					// 如果新告警等级严重性低于已有告警等级，关闭已有告警，创建新告警
					if alarmLevel > existingAlarm.LevelID {
						existingAlarm.Status = entity.INACTIVE
						existingAlarm.ModifyTime = time.Now()
						alarmList = append(alarmList, existingAlarm)
					}
				}
				// 添加到告警列表
				alarmList = append(alarmList, alarmInfo)
				// 更新告警管理器
				constants.GlobalAlarmManager.SetAlarm(diskState.HostName, alarmInfo)
			} else {
				//没有产生告警，检查是否需要告警恢复
				existingAlarm, exists := constants.GlobalAlarmManager.GetAlarm(diskState.HostName, entity.DISK_ERROR)
				if exists {
					// 设置告警为非活跃状态
					existingAlarm.Status = entity.INACTIVE
					existingAlarm.ModifyTime = time.Now()
					alarmList = append(alarmList, existingAlarm)
					// 更新告警管理器
					constants.GlobalAlarmManager.SetAlarm(diskState.HostName, existingAlarm)
				}
			}
		}
	}
	//处理内存告警
	if utils.LLen(constants.MEM_STATE_LIST) > 0 {
		memStateJsonStr := utils.LRange(constants.MEM_STATE_LIST, 0, -1)
		utils.Del(constants.MEM_STATE_LIST)
		latestMemMap := make(map[string]entity.MemState)
		for i := range memStateJsonStr {
			if memStateJsonStr[i] != "" {
				var memState entity.MemState
				err := json.Unmarshal([]byte(memStateJsonStr[i]), &memState)
				if err != nil {
					logging.Error("解析内存状态数据失败:" + err.Error())
				}
				if _, exists := latestMemMap[memState.HostName]; !exists || memState.CreateTime.After(latestMemMap[memState.HostName].CreateTime.Time) {
					latestMemMap[memState.HostName] = memState
				}
			}
		}

		for _, memState := range latestMemMap {
			alarmThreshold, exists := alarmThresholdMap[memState.HostName]
			var alarmLevel int
			var alramDetail string
			if exists {
				if memState.UsePer > float64(alarmThreshold.MemoryMax) && alarmThreshold.MemoryMaxEnable == 1 {
					alarmLevel = 1
					alramDetail = "一级告警:" + memState.HostName + ";内存使用率:" + strconv.FormatFloat(memState.UsePer, 'f', -1, 64) + ">" + strconv.Itoa(alarmThreshold.MemoryMax)
				} else if memState.UsePer > float64(alarmThreshold.MemoryNor) && alarmThreshold.MemoryNorEnable == 1 {
					alarmLevel = 2
					alramDetail = "二级告警:" + memState.HostName + ";内存使用率:" + strconv.FormatFloat(memState.UsePer, 'f', -1, 64) + ">" + strconv.Itoa(alarmThreshold.MemoryNor)
				} else if memState.UsePer > float64(alarmThreshold.MemoryMin) && alarmThreshold.MemoryMinEnable == 1 {
					alarmLevel = 3
					alramDetail = "三级告警:" + memState.HostName + ";内存使用率:" + strconv.FormatFloat(memState.UsePer, 'f', -1, 64) + ">" + strconv.Itoa(alarmThreshold.MemoryMin)
				}
			}
			//告警更新原则: 告警等级上升则更新告警记录即可，告警等级下降的过程，关闭高级告警，新增一条当前等级的告警记录
			//告警等级>0 说明有告警产生
			if alarmLevel > 0 {
				// 创建或更新告警信息
				alarmInfo := entity.AlarmInfo{
					ID:         uuid.NewString(),
					LevelID:    alarmLevel,
					Detail:     alramDetail,
					HostIP:     memState.HostName,
					Type:       entity.MEMORY_ERROR,
					CreateTime: time.Now(),
					ModifyTime: time.Now(),
					Status:     entity.ACTIVE,
					Flag:       memState.Type,
				}
				// 检查是否已存在该类型告警
				existingAlarm, exists := constants.GlobalAlarmManager.GetAlarm(memState.HostName, entity.MEMORY_ERROR)
				if exists {
					// 如果已存在告警，保留原ID和创建时间
					alarmInfo.ID = existingAlarm.ID
					alarmInfo.CreateTime = existingAlarm.CreateTime

					// 如果新告警等级严重性低于已有告警等级，关闭已有告警，创建新告警
					if alarmLevel > existingAlarm.LevelID {
						existingAlarm.Status = entity.INACTIVE
						existingAlarm.ModifyTime = time.Now()
						alarmList = append(alarmList, existingAlarm)
					}
				}
				// 添加到告警列表
				alarmList = append(alarmList, alarmInfo)
				// 更新告警管理器
				constants.GlobalAlarmManager.SetAlarm(memState.HostName, alarmInfo)
			} else {
				//没有产生告警，检查是否需要告警恢复
				existingAlarm, exists := constants.GlobalAlarmManager.GetAlarm(memState.HostName, entity.MEMORY_ERROR)
				if exists {
					// 设置告警为非活跃状态
					existingAlarm.Status = entity.INACTIVE
					existingAlarm.ModifyTime = time.Now()
					alarmList = append(alarmList, existingAlarm)
					// 更新告警管理器
					constants.GlobalAlarmManager.SetAlarm(memState.HostName, existingAlarm)
				}
			}
		}
	}
	logging.Info("告警数据如下:", alarmList)
	// 开始事务
	tx := db.Begin()
	defer func() {
		if r := recover(); r != nil {
			tx.Rollback()
			logging.Error("发生panic,事务已回滚:", r)
		}
	}()
	//保存、更新告警数据
	if len(alarmList) > 0 {
		result := tx.Clauses(clause.OnConflict{
			Columns:   []clause.Column{{Name: "id"}},
			DoUpdates: clause.AssignmentColumns([]string{"status", "modify_time", "level_id", "detail"}),
		}).CreateInBatches(&alarmList, 1000)
		if result.Error != nil {
			tx.Rollback()
			logging.Error("保存告警数据失败:" + tx.Error.Error())
			return
		}
	}

	// 使用告警管理器更新 SystemInfo 表
	activeHosts := constants.GlobalAlarmManager.GetAllActiveHosts()
	inactiveHosts := constants.GlobalAlarmManager.GetAllInactiveHosts()

	// 更新 SystemInfo 表中的 AlarmState 字段
	if len(activeHosts) > 0 {
		logging.Info("激活告警状态主机如下:", activeHosts)
		if err := tx.Model(entity.SystemInfo{}).Where("host_name in ?", activeHosts).Update("alarm_state", entity.ABNORMAL).Error; err != nil {
			tx.Rollback()
			logging.Error("更新活跃告警状态失败：" + err.Error())
			return
		}
	}
	if len(inactiveHosts) > 0 {
		logging.Info("关闭告警状态主机如下:", inactiveHosts)
		if err := tx.Model(entity.SystemInfo{}).Where("host_name in ?", inactiveHosts).Update("alarm_state", entity.NORMAL).Error; err != nil {
			tx.Rollback()
			logging.Error("更新非活跃告警状态失败：" + err.Error())
			return
		}
	}
	// 提交事务
	if err := tx.Commit().Error; err != nil {
		tx.Rollback()
		logging.Error("提交事务失败：" + err.Error())
		return
	}
	logging.Info("批量提交监控数据耗时:" + time.Since(start).String())
}

// 增量初始化告警管理器
func incrementalInitializeAlarmManager() {
	// 获取数据库连接
	db := utils.GetDB()
	if db == nil {
		logging.Error("数据库连接失败，跳过commitTask")
		return
	}

	// 设置最小初始化间隔（例如5分钟）
	minInterval := 10 * time.Minute

	// 如果距离上次初始化时间不足最小间隔，则跳过
	if time.Since(lastInitTime) < minInterval {
		return
	}

	// 记录当前时间
	currentTime := time.Now()

	// 查询自上次初始化以来变更的告警记录
	var changedAlarms []entity.AlarmInfo
	if !lastInitTime.IsZero() {
		//根本性地解决了由于增量初始化导致的内存状态混乱问题
		db.Where("modify_time > ? AND status = ?", lastInitTime, entity.ACTIVE).Find(&changedAlarms)
	} else {
		// 首次初始化，加载所有活跃告警
		db.Where("status = ?", entity.ACTIVE).Find(&changedAlarms)
	}

	// 更新告警管理器
	for _, alarm := range changedAlarms {
		constants.GlobalAlarmManager.SetAlarm(alarm.HostIP, alarm)
	}

	// 更新上次初始化时间
	lastInitTime = currentTime
	logging.Info("告警管理器增量初始化完成，处理了", len(changedAlarms), "条告警记录")
}
